use std::sync::Arc;
use std::fs::OpenOptions;
use std::path::Path;
use std::sync::RwLock;

use log::{info, warn, error, debug, LevelFilter};
use fern::colors::{Color, ColoredLevelConfig};
use clap::Parser;
use mailtutan_lib::*;
use mailtutan_lib::storage::Storage;

mod config;
use crate::config::StorageType;
use config::Config;

use tokio::sync::broadcast;
use tokio::{self, runtime::Builder, signal};

#[tokio::main]
async fn main() {
    // 初始化日志
    if let Err(e) = setup_logging() {
        eprintln!("日志初始化失败: {}", e);
        return;
    }
    info!("Mailtutan 应用启动中...");

    // 解析配置
    let config = Config::parse();
    info!("加载配置完成: {:?}", config);
    debug!("详细配置: {:#?}", config);

    // 提前克隆web_hook配置，避免后续移动后无法访问
    let web_hook = config.web_hook.clone();

    // 创建Tokio运行时
    info!("创建多线程Tokio运行时");
    let runtime = match Builder::new_multi_thread().enable_all().build() {
        Ok(rt) => {
            info!("Tokio运行时创建成功");
            rt
        }
        Err(e) => {
            error!("Tokio运行时创建失败: {}", e);
            return;
        }
    };

    // 初始化存储
    info!("初始化存储，类型: {:?}", config.storage);
    let storage: Box<RwLock<dyn Storage + 'static>> = match config.storage {
        StorageType::Memory => {
            info!("使用内存存储，消息上限: {}", config.messages_limit);
            Box::new(RwLock::new(storage::Memory::new(config.messages_limit)))
        }
        StorageType::Maildir => {
            info!(
                "使用Maildir存储，路径: '{}'，消息上限: {}",
                config.maildir_path,
                config.messages_limit
            );
            let memdir = storage::Memdir::new(config.messages_limit, config.maildir_path);
            Box::new(RwLock::new(memdir))
        }
    };

    // 创建应用状态
    info!("创建应用全局状态");
    let (broadcast_sender, _) = broadcast::channel(100);
    let state = Arc::new(AppState {
        storage,
        channel: broadcast_sender,
        messages_limit: config.messages_limit,
        smtp_auth_username: config.smtp_auth_username.clone(),
        smtp_auth_password: config.smtp_auth_password.clone(),
        http_auth_username: config.http_username,
        http_auth_password: config.http_password,
        web_hook: config.web_hook,  // 此处发生值移动
    });
    info!("应用状态创建成功");

    // 初始化API服务器 - 移除不必要的mut
    info!("初始化API服务器");
    let api_bind_addr = (config.ip.clone(), config.http_port);
    let api_server_builder = api::Builder::new()
        .http_auth(config.http_auth)
        .bind(api_bind_addr.into())
        .with_state(state.clone());

    let api_server = api_server_builder.build();

    // 初始化SMTP服务器
    info!("初始化SMTP服务器");
    let smtp_bind_addr = (config.ip.clone(), config.smtp_port);
    let mut smtp_server_builder = smtp::Builder::new()
        .with_state(state.clone())
        .with_auth(config.smtp_auth_username.is_some() && config.smtp_auth_password.is_some())
        .bind(smtp_bind_addr.into());

    match (config.smtp_cert_path, config.smtp_key_path) {
        (Some(cert), Some(key)) => {
            info!("SMTP启用SSL，证书路径: '{}'，密钥路径: '{}'", cert, key);
            smtp_server_builder = smtp_server_builder.with_ssl(Some(cert), Some(key));
        }
        _ => {
            warn!("SMTP未启用SSL，生产环境建议配置证书");
        }
    }

    let smtp_server = smtp_server_builder.build();

    // 初始化Web Hook工作器 - 使用提前克隆的web_hook
    let web_hook_worker = web_hook::Worker::new(state.clone());
    if web_hook.is_some() {
        info!("Web Hook工作器初始化，目标地址: {:?}", web_hook);
    } else {
        info!("未配置Web Hook，工作器处于空闲状态");
    }

    // 启动服务
    info!("启动API服务器，地址: http://{}:{}", api_bind_addr.0, api_bind_addr.1);
    let api_handle = runtime.spawn(api_server.serve());

    info!("启动SMTP服务器，地址: smtp://{}:{}", smtp_bind_addr.0, smtp_bind_addr.1);
    let smtp_handle = runtime.spawn(smtp_server.serve());

    info!("启动Web Hook工作器");
    let web_hook_handle = runtime.spawn(web_hook_worker.serve());

    // 等待关闭信号
    info!("应用启动成功，等待关闭信号（Ctrl+C）");
    tokio::select! {
        res = api_handle => match res {
            Ok(_) => info!("API服务器正常停止"),
            Err(e) => error!("API服务器任务失败: {}", e),
        },
        res = smtp_handle => match res {
            Ok(_) => info!("SMTP服务器正常停止"),
            Err(e) => error!("SMTP服务器任务失败: {}", e),
        },
        res = web_hook_handle => match res {
            Ok(_) => info!("Web Hook工作器正常停止"),
            Err(e) => error!("Web Hook工作器任务失败: {}", e),
        },
        _ = signal::ctrl_c() => info!("收到Ctrl+C信号，开始关闭应用"),
    }

    // 关闭运行时
    info!("正在关闭Tokio运行时");
    runtime.shutdown_background();
    info!("应用关闭完成");
}

/// 日志配置
fn setup_logging() -> Result<(), fern::InitError> {
    // 创建日志目录
    let log_dir = Path::new("logs");
    if !log_dir.exists() {
        std::fs::create_dir(log_dir)?;
    }

    // 日志文件路径
    let log_file_path = log_dir.join(format!(
        "mailtutan_{}.log",
        chrono::Local::now().format("%Y%m%d_%H%M%S")
    ));

    // 日志级别颜色配置
    let colored_level = ColoredLevelConfig::new()
        .error(Color::Red)
        .warn(Color::Yellow)
        .info(Color::Green)
        .debug(Color::Blue)
        .trace(Color::Cyan);

    // 配置日志
    fern::Dispatch::new()
        .level(LevelFilter::Debug)
        .format(move |out, message, record| {
            out.finish(format_args!(
                "[{}] [{}] [{}] {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"),
                record.target(),
                colored_level.color(record.level()),
                message
            ))
        })
        // 输出到文件
        .chain(
            OpenOptions::new()
                .create(true)
                .append(true)
                .open(log_file_path.clone())?
        )
        // 输出到控制台
        .chain(
            fern::Dispatch::new()
                .level(LevelFilter::Info)
                .chain(std::io::stdout())
        )
        .apply()?;

    info!("日志初始化完成，日志文件路径: {}", log_file_path.display());
    Ok(())
}
